/*
 * Copyright 2006-2008 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.martinimix.dao.order;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import net.martinimix.beans.bind.BindingService;
import net.martinimix.dao.BusinessActionChainInput;
import net.martinimix.dao.BusinessActionChainTemplate;
import net.martinimix.dao.BusinessActionInvocationException;
import net.martinimix.domain.order.Cart;
import net.martinimix.domain.order.Order;
import net.martinimix.domain.order.OrderHeader;
import net.martinimix.domain.order.OrderLine;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.bluemartini.dna.BMContext;
import com.bluemartini.dna.BMThreadManager;
import com.bluemartini.dna.BusinessObject;
import com.bluemartini.dna.BusinessObjectArray;
import com.bluemartini.dna.DNAIntegerArray;
import com.bluemartini.dna.DNAList;
import com.bluemartini.webconnect.WebConnect;

/**
 * Provides a business action chain to finalize and save an order.
 * 
 * @author Scott Rossillo
 *
 */
final class FinalizeOrderActionChain extends BusinessActionChainTemplate {
	
	private final static Log log = LogFactory.getLog(FinalizeOrderActionChain.class);
	
	/**
	 * Creates a new save order action chain.
	 * 
	 * @param bindingService
	 */
	public FinalizeOrderActionChain(BindingService bindingService) {
		super(bindingService);
	}

	private DNAList createInput(Order order, Cart cart) {
		
		final Map input = new LinkedHashMap();
		final OrderHeader header = order.getOrderHeader();
		
		// need to prep the plan ships first (don't move)
		final BusinessObjectArray planShipArray = 
			preparePlannedShipments(order.getPlannedShipments(), order.getOrderLines());
		
		// BM puts the account from the thread manager as the customer
		// this makes not sense, but the line below fixes it
		BMThreadManager.setUserAccountID(order.getCustomer().getId());
		
		input.put(WebConnect.SESSION_CURRENT_USER, order.getCustomer());
		input.put(WebConnect.SESSION_ORDER, header);
		input.put(WebConnect.SESSION_ORDER_LINE_ARRAY, order.getOrderLines());
		
		// why does BM need the cart to create an order?
		input.put(WebConnect.SESSION_CART_ITEM_ARRAY, cart.getCartItems());
		
		DNAList dna = businessActionToolkit.createBusinessActionInput(input, false);
		
		// this is even worse :P
		if(order.getOrderHeader().getShipMethodId() == null) {
			throw new BusinessActionInvocationException("[order.orderHeader.shipMethodId] cannot be null!");
		}
		
		if(order.getShippingAddress().getId() == null) {
			throw new BusinessActionInvocationException("[order.shippingAddress] cannot be null!");
		}
		
		BusinessObject generic = BMContext.createBusinessObject("GENERIC");
		generic.setLong("shippingMethodList", order.getOrderHeader().getShipMethodId());
		generic.setLong("selectAddressList", order.getShippingAddress().getId());
		
		dna.setBusinessObjectRef("GENERIC", generic);
		
		// add the planned shipment (done here to manipulate)
		dna.setBusinessObjectArray(
				WebConnect.SESSION_PLAN_SHIPMENT_ARRAY, 
				planShipArray);
		
		if(log.isDebugEnabled()) {
			log.error("Finalizing order with input: \n" + dna);
		}
		
		return dna;
	}
	
	private BusinessObjectArray preparePlannedShipments(List plannedShipments, List orderLines) {
		
		final BusinessObjectArray planShipArray = 
			bindingService.bindBusinessObjects(plannedShipments, "PLAN_SHIPMENT");
		
		// FIXME: we only support one planned shipment at this time
		for(int i = 0; i < planShipArray.size(); i++) {
			
			BusinessObject planShip = planShipArray.elementAt(i);
			DNAIntegerArray orderLineIndex = new DNAIntegerArray();
			
			for(int j = 0; j < orderLines.size(); j++) {
				
				OrderLine orderLine = (OrderLine) orderLines.get(j);
				orderLineIndex.addElement(j);
				
				orderLine.setPlanShipmentIndex(new Integer(i));
			}
			
			planShip.setIntegerArrayRef("orderLineIndex", orderLineIndex);
		}
		
		return planShipArray;
	}
	
	public void saveOrder(Order order, Cart cart) {
		
		String actions[] = new String[] {
				//"WebConnectCreatePlanShipments",
				"FinalizeOrder"
		};
		
		BusinessActionChainInput chain = new BusinessActionChainInput(createInput(order, cart));
		
		DNAList response = super.doChain(actions, chain);
		
		log.info("Saved order, response is: " + response);
		
	}

}
